package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"unsafe"
	"log"
	"net"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"
)

// 定义协议结构体
type TcpAsuCmd struct {
	HdFg       [8]byte
	CmdType    uint16
	RespCmdFg  uint8
	FgAsuSvrOp uint8
	DevHwId    uint32
	Seq        uint32
	Resv       [6]byte
	Len        uint16
	CrcHd      uint16
	CrcData    uint16
	Data       [480]byte
}

// 计算校验和
func (cmd *TcpAsuCmd) CalculateChecksums() {
	// 保存原始值
	//originalCrcHd := cmd.CrcHd
	//originalCrcData := cmd.CrcData

	// 置零后计算
	cmd.CrcHd = 0
	cmd.CrcData = 0

	// 将结构体转换为字节切片
	buf := new(bytes.Buffer)
	if err := binary.Write(buf, binary.LittleEndian, cmd); err != nil {
		log.Printf("CalculateChecksums error: %v", err)
		return
	}
	bytesData := buf.Bytes()

	// 计算头部校验 (0-27字节)
	calcHd := uint16(0)
	for i := 0; i < 28; i++ { // offsetof(TcpAsuCmd, crc_hd) 为28
		calcHd ^= uint16(bytesData[i])
	}

	// 计算数据校验 (32-511字节)
	calcData := uint16(0)
	for i := 32; i < len(bytesData); i++ {
		calcData += uint16(bytesData[i])
	}

	// 设置计算值
	cmd.CrcHd = calcHd
	cmd.CrcData = calcData
	log.Printf("cmd.CrcHd: %v; cmd.CrcData: %v", cmd.CrcHd, cmd.CrcData)

	// 恢复原始值（如果需要）
	//cmd.CrcHd = originalCrcHd
	//cmd.CrcData = originalCrcData
}

// 验证校验和
func (cmd *TcpAsuCmd) ValidateChecksums() bool {
	// 创建临时副本
	tmp := *cmd
	tmp.CrcHd = 0
	tmp.CrcData = 0

	// 将结构体转换为字节切片
	buf := new(bytes.Buffer)
	if err := binary.Write(buf, binary.LittleEndian, &tmp); err != nil {
		log.Printf("ValidateChecksums error: %v", err)
		return false
	}
	bytesData := buf.Bytes()

	// 计算头部校验
	calcHd := uint16(0)
	for i := 0; i < 28; i++ {
		calcHd ^= uint16(bytesData[i])
	}

	// 计算数据校验
	calcData := uint16(0)
	for i := 32; i < len(bytesData); i++ {
		calcData += uint16(bytesData[i])
	}

	log.Printf("cmd.CrcHd: %v; cmd.CrcData: %v", cmd.CrcHd, cmd.CrcData)
	log.Printf("calcHd: %v; calcData: %v", calcHd, calcData)
	// 比较计算结果
	return calcHd == cmd.CrcHd && calcData == cmd.CrcData
}
// PrintHexDump 打印16进制格式
func (t *TcpAsuCmd) PrintHexDump() {
	// 将结构体转换为字节切片
	bytes := (*[unsafe.Sizeof(TcpAsuCmd{})]byte)(unsafe.Pointer(t))[:]
	size := len(bytes)
	
	for i := 0; i < size; i++ {
		// 每16字节换行并打印偏移量
		if i%16 == 0 {
			if i > 0 {
				fmt.Println()
			}
			fmt.Printf("%04x: ", i)
		}
		
		// 打印当前字节的16进制表示
		fmt.Printf("%02x ", bytes[i])
	}
	fmt.Printf("\nTotal size: %d bytes\n", size)
}

// 报警日志数据结构
type AlarmLogData struct {
	DeviceId     uint32
	User         [32]byte
	SecBgn1       uint64
	//SecBgn2       uint32
	UsecBgn      uint32
	SecEnd1      uint32
	SecEnd2      uint32
	UsecEnd      uint32
	Solve        uint32
	SensorGrpIdx uint32
	Reserved2    uint32
	Reserved3    uint32
}

// 命令响应标志
const (
	CMD_FLAG  = 0
	RESP_FLAG = 1
)

// 客户端类型
const (
	ASU_CLIENT      = 1
	SVR_CLIENT      = 2
	OPERATOR_CLIENT = 3
)

// 命令ID
const (
	HEARTBEAT_CMD   = 0xBBEA
	ALARM_CMD       = 0xAAD
	FAULT_CMD       = 0xFAD
	PARAM_CFG_CMD   = 0xCFC
	PARAM_CFG_RESP  = 0xCFE
	ALARM_NOTIFY    = 0xAAF
	FAULT_NOTIFY    = 0xFAD
	QUIT_CMD        = 0xEEEE
	ALARM_RESOLVE   = 0xAAE
)

// TCP头部标识
var TCP_HEADER = [8]byte{'S', 'H', 'E', 'N', 'G', 'X', 'U', 'E'}

// 最大时间值
const MAX_TIME = 4102416000 // 2100-01-01 00:00:00

// Session 表示一个客户端连接
type Session struct {
	Conn         net.Conn
	ClientType   uint8
	Server       *Server
	Active       bool
	Mutex        sync.Mutex
	ShutdownFlag *bool
}

// 解析报警日志数据
func parseAlarmLogData(data []byte) *AlarmLogData {
	alarm := &AlarmLogData{}
	
	// 使用小端序解析
	alarm.DeviceId = binary.LittleEndian.Uint32(data[0:4])
	copy(alarm.User[:], data[4:36])
	alarm.SecBgn1 = uint64(binary.LittleEndian.Uint64(data[36:44]))
	log.Printf("parseAlarmLogData valid sec_bgn1: %d", alarm.SecBgn1)
	//secBgn := int64(binary.LittleEndian.Uint64(data))
	//alarm.SecBgn2 = uint32(binary.LittleEndian.Uint32(data[40:44]))
	alarm.UsecBgn = uint32(binary.LittleEndian.Uint32(data[44:48]))
	alarm.UsecEnd = uint32(binary.LittleEndian.Uint32(data[56:60]))
	alarm.Solve = binary.LittleEndian.Uint32(data[60:64])
	alarm.SensorGrpIdx = binary.LittleEndian.Uint32(data[64:68])
	alarm.Reserved2 = binary.LittleEndian.Uint32(data[68:72])
	alarm.Reserved3 = binary.LittleEndian.Uint32(data[72:76])
	
	return alarm
}

// NewSession 创建新的会话
func NewSession(conn net.Conn, server *Server, shutdownFlag *bool) *Session {
	return &Session{
		Conn:         conn,
		Server:       server,
		Active:       true,
		ShutdownFlag: shutdownFlag,
	}
}

// Start 启动会话处理
func (s *Session) Start() {
	defer s.Conn.Close()
	defer s.Server.RemoveSession(s)
	
	buffer := make([]byte, 1024)
	
	for {
		if *s.ShutdownFlag {
			return
		}
		
		n, err := s.Conn.Read(buffer)
		if err != nil {
			log.Printf("Read error: %v", err)
			return
		}
		
		if n < 512 { // TcpAsuCmd 大小为 512 字节
			log.Printf("Received incomplete packet: %d bytes", n)
			continue
		}
		
		// 解析命令
		var cmd TcpAsuCmd
		buf := bytes.NewReader(buffer[:512])
		if err := binary.Read(buf, binary.LittleEndian, &cmd); err != nil {
			log.Printf("Binary read error: %v", err)
			continue
		}
		cmd.PrintHexDump()
		
		// 验证校验和
		if !cmd.ValidateChecksums() {
			log.Println("Invalid checksums in received command!")
			continue
		}
		
		log.Printf("Received valid TcpAsuCmd: hd_fg=%s dev_hw_id=0x%x cmdtype=0x%x",
			cmd.HdFg, cmd.DevHwId, cmd.CmdType)
		
		// 记录客户端类型
		s.ClientType = cmd.FgAsuSvrOp
		
		// 处理不同命令
		switch cmd.CmdType {
		case QUIT_CMD:
			log.Println("Received quit command, closing connection...")
			return
			
		case ALARM_CMD, FAULT_CMD:
			log.Println("Received alarm command...")
			s.saveAlarmToDatabase(cmd)
			s.notifyOperatorStation(cmd)
			
			// 解析报警数据
			/*
			#if 0
			var alarmData AlarmLogData
			alarmBuf := bytes.NewReader(cmd.Data[:])
			if err := binary.Read(alarmBuf, binary.LittleEndian, &alarmData); err != nil {
				log.Printf("Alarm data parse error: %v", err)
			} else {
				alarm := parseAlarmLogData(alarmBuf)
				printAlarmLogData(alarm)
			}
			#endif
			*/
			alarm := parseAlarmLogData(cmd.Data[:])
			printAlarmLogData(alarm)
			
		case PARAM_CFG_CMD:
			s.saveParametersToDatabase(cmd)
		}
		
		// 发送响应
		respCmd := cmd
		copy(respCmd.HdFg[:], "RESP")
		respCmd.RespCmdFg = RESP_FLAG
		respCmd.CalculateChecksums()
		respCmd.PrintHexDump()
		
		if err := binary.Write(s.Conn, binary.LittleEndian, respCmd); err != nil {
			log.Printf("Write response error: %v", err)
			return
		}
	}
}

// 保存报警到数据库
func (s *Session) saveAlarmToDatabase(cmd TcpAsuCmd) {
	log.Println("Saving alarm to database...")
	// 实际实现中这里会有数据库操作
}

// 通知操作员站
func (s *Session) notifyOperatorStation(cmd TcpAsuCmd) {
	log.Println("Notifying operator station...")
	
	// 构造通知命令
	notifyCmd := TcpAsuCmd{
		HdFg:       TCP_HEADER,
		RespCmdFg:  CMD_FLAG,
		DevHwId:    cmd.DevHwId,
		FgAsuSvrOp: SVR_CLIENT,
	}
	
	if cmd.CmdType == ALARM_CMD {
		notifyCmd.CmdType = ALARM_NOTIFY
	} else if cmd.CmdType == FAULT_CMD {
		notifyCmd.CmdType = FAULT_NOTIFY
	} else {
		log.Printf("Invalid cmdtype for notification: 0x%x", cmd.CmdType)
		return
	}
	
	notifyCmd.Len = uint16(len(cmd.Data))
	copy(notifyCmd.Data[:], cmd.Data[:])
	notifyCmd.CalculateChecksums()
	
	// 发送给所有操作员站
	s.Server.SendToOperatorStations(notifyCmd)
}

// 保存参数到数据库
func (s *Session) saveParametersToDatabase(cmd TcpAsuCmd) {
	log.Println("Saving parameters to database...")
	// 实际实现中这里会有数据库操作
}

// Server 表示TCP服务器
type Server struct {
	Listener     net.Listener
	Sessions     map[*Session]bool
	SessionsMutex sync.Mutex
	ShutdownFlag bool
	Port         int
}

// NewServer 创建新的服务器
func NewServer(port int) *Server {
	return &Server{
		Port:     port,
		Sessions: make(map[*Session]bool),
	}
}

// Start 启动服务器
func (s *Server) Start() error {
	listener, err := net.Listen("tcp", fmt.Sprintf(":%d", s.Port))
	if err != nil {
		return fmt.Errorf("failed to listen: %v", err)
	}
	s.Listener = listener
	
	log.Printf("Server started on port %d", s.Port)
	
	// 处理关闭信号
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
	
	go func() {
		<-signalChan
		log.Println("\nShutting down server...")
		s.Shutdown()
	}()
	
	// 接受连接
	for {
		conn, err := s.Listener.Accept()
		if err != nil {
			if s.ShutdownFlag {
				return nil
			}
			log.Printf("Accept error: %v", err)
			continue
		}
		
		if s.ShutdownFlag {
			conn.Close()
			return nil
		}
		
		// 检查最大连接数
		if len(s.Sessions) >= 32 {
			log.Println("Server busy, rejecting new connection")
			conn.Close()
			continue
		}
		
		// 创建新会话
		session := NewSession(conn, s, &s.ShutdownFlag)
		s.AddSession(session)
		go session.Start()
	}
}

// AddSession 添加会话
func (s *Server) AddSession(session *Session) {
	s.SessionsMutex.Lock()
	defer s.SessionsMutex.Unlock()
	s.Sessions[session] = true
	log.Printf("New connection. Active sessions: %d", len(s.Sessions))
}

// RemoveSession 移除会话
func (s *Server) RemoveSession(session *Session) {
	s.SessionsMutex.Lock()
	defer s.SessionsMutex.Unlock()
	delete(s.Sessions, session)
	log.Printf("Connection closed. Active sessions: %d", len(s.Sessions))
}

// SendToOperatorStations 发送消息给所有操作员站
func (s *Server) SendToOperatorStations(cmd TcpAsuCmd) {
	s.SessionsMutex.Lock()
	defer s.SessionsMutex.Unlock()
	
	for session := range s.Sessions {
		if session.ClientType == OPERATOR_CLIENT {
			if err := binary.Write(session.Conn, binary.LittleEndian, cmd); err != nil {
				log.Printf("Send to operator error: %v", err)
			} else {
				log.Println("Sent alarm notification to operator station")
			}
		}
	}
}

// Shutdown 关闭服务器
func (s *Server) Shutdown() {
	s.ShutdownFlag = true
	
	// 关闭监听器
	if s.Listener != nil {
		s.Listener.Close()
	}
	
	// 关闭所有会话
	s.SessionsMutex.Lock()
	defer s.SessionsMutex.Unlock()
	for session := range s.Sessions {
		session.Conn.Close()
	}
	s.Sessions = make(map[*Session]bool)
	
	log.Println("Server exited normally.")
}

/*
// 打印报警日志数据
func printAlarmLogData(alarm *AlarmLogData) {
	if alarm.SecBgn > MAX_TIME || alarm.SecBgn < 0 {
		log.Printf("Invalid sec_bgn: %d", alarm.SecBgn)
		return
	}
	
	t := time.Unix(alarm.SecBgn, int64(alarm.UsecBgn)*1000)
	log.Printf("AlarmLogData: DeviceID=%d User=%s Time=%s Solve=%d",
		alarm.DeviceId, alarm.User[:], t.Format(time.RFC3339), alarm.Solve)
}
*/

/*
// 打印报警日志数据
func printAlarmLogData(alarm *AlarmLogData) {
	// 检查开始时间是否有效

	secBgn := int64(binary.LittleEndian.Uint64(alarm.SecBgn[:]))
	if secBgn > MAX_TIME || secBgn < 0 {
		log.Printf("Invalid sec_bgn: %d", secBgn)
		return
	}
	
	// 转换开始时间
	tmBgn := time.Unix(secBgn, int64(alarm.UsecBgn*1000)) // 微秒转纳秒
	timeBgnStr := tmBgn.Format("2006-01-02 15:04:05.000000")
	
	// 检查结束时间是否有效
	secEnd := int64(binary.LittleEndian.Uint64(alarm.SecEnd[:]))
	if secEnd > MAX_TIME || secEnd < 0 {
		log.Printf("Invalid sec_end: %d", secEnd)
		return
	}
	
	// 转换结束时间
	tmEnd := time.Unix(secEnd, int64(alarm.UsecEnd*1000)) // 微秒转纳秒
	timeEndStr := tmEnd.Format("2006-01-02 15:04:05.000000")
	
	// 打印所有属性
	fmt.Printf("device_id  : %d\n", alarm.DeviceId)
	fmt.Printf("user       : %s\n", bytesToString(alarm.User[:]))
	fmt.Printf("sec_bgn    : %s\n", timeBgnStr)
	fmt.Printf("sec_end    : %s\n", timeEndStr)
	fmt.Printf("solve      : %d\n", alarm.Solve)
	fmt.Printf("sensor_grp_idx  : %d\n", alarm.SensorGrpIdx)
	fmt.Printf("reserved2  : %d\n", alarm.Reserved2)
	fmt.Printf("reserved3  : %d\n", alarm.Reserved3)
}
*/

// 辅助函数：将字节切片转换为字符串（去除空字符）
func bytesToString(b []byte) string {
	for i, c := range b {
		if c == 0 {
			return string(b[:i])
		}
	}
	return string(b)
}
/*
// 打印报警日志数据
func printAlarmLogData(alarm *AlarmLogData) {
	if alarm.SecBgn1 > MAX_TIME || alarm.SecBgn1 < 0 {
		log.Printf("Invalid sec_bgn1: %d", alarm.SecBgn1)
		return
	}
	
	tmBgn := time.Unix(alarm.SecBgn1, uint32(alarm.UsecBgn1)*1000)
	timeBgnStr := tmBgn.Format("2006-01-02 15:04:05.000000")
	
	if alarm.SecEnd1 > MAX_TIME || alarm.SecEnd1 < 0 {
		log.Printf("Invalid sec_end1: %d", alarm.SecEnd1)
		return
	}
	
	tmEnd := time.Unix(alarm.SecEnd1, uint32(alarm.UsecEnd1)*1000)
	timeEndStr := tmEnd.Format("2006-01-02 15:04:05.000000")
	
	fmt.Printf("device_id  : %d\n", alarm.DeviceId)
	fmt.Printf("user       : %s\n", bytesToString(alarm.User[:]))
	fmt.Printf("sec_bgn    : %s\n", timeBgnStr)
	fmt.Printf("sec_end    : %s\n", timeEndStr)
	fmt.Printf("solve      : %d\n", alarm.Solve)
	fmt.Printf("sensor_grp_idx  : %d\n", alarm.SensorGrpIdx)
	fmt.Printf("reserved2  : %d\n", alarm.Reserved2)
	fmt.Printf("reserved3  : %d\n", alarm.Reserved3)
}
*/
func printAlarmLogData(alarm *AlarmLogData) {
	// 检查开始时间是否有效

	//secBgn := int64(binary.LittleEndian.Uint64(alarm.SecBgn1))
	//log.Printf("valid secBgn: %d", secBgn)

	if alarm.SecBgn1 > MAX_TIME || alarm.SecBgn1 < 0 {
		log.Printf("Invalid sec_bgn1: %d", alarm.SecBgn1)
		return
	}
	log.Printf("valid sec_bgn1: %d", alarm.SecBgn1)

	//log.Printf("valid sec_bgn2: %d", alarm.SecBgn2)
	
	// 修复1: 使用正确的字段名 SecBgn1 和 UsecBgn1
	// 修复2: 将秒数转换为 int64（如果它是 uint32）
	// 修复3: 将微秒转换为纳秒时使用 int64
	tmBgn := time.Unix(int64(alarm.SecBgn1), int64(alarm.UsecBgn)*1000)
	timeBgnStr := tmBgn.Format("2006-01-02 15:04:05.000000")
	
	// 检查结束时间是否有效
	if alarm.SecEnd1 > MAX_TIME || alarm.SecEnd1 < 0 {
		log.Printf("Invalid sec_end1: %d", alarm.SecEnd1)
		return
	}
	
	// 修复1: 使用正确的字段名 SecEnd1 和 UsecEnd1
	// 修复2: 将秒数转换为 int64（如果它是 uint32）
	// 修复3: 将微秒转换为纳秒时使用 int64
	tmEnd := time.Unix(int64(alarm.SecEnd1), int64(alarm.UsecEnd)*1000)
	timeEndStr := tmEnd.Format("2006-01-02 15:04:05.000000")
	
	fmt.Printf("device_id  : %d\n", alarm.DeviceId)
	fmt.Printf("user       : %s\n", bytesToString(alarm.User[:]))
	fmt.Printf("sec_bgn    : %s\n", timeBgnStr)
	fmt.Printf("sec_end    : %s\n", timeEndStr)
	fmt.Printf("solve      : %d\n", alarm.Solve)
	fmt.Printf("sensor_grp_idx  : %d\n", alarm.SensorGrpIdx)
	fmt.Printf("reserved2  : %d\n", alarm.Reserved2)
	fmt.Printf("reserved3  : %d\n", alarm.Reserved3)
}

func main() {
	if len(os.Args) != 2 {
		log.Fatal("Usage: go run main.go <port>")
	}
	
	port := 0
	if _, err := fmt.Sscanf(os.Args[1], "%d", &port); err != nil {
		log.Fatalf("Invalid port: %v", err)
	}
	
	server := NewServer(port)
	if err := server.Start(); err != nil {
		log.Fatalf("Server error: %v", err)
	}
}

/*
00 00 00 00 63 fa cc 68

*/